package tv.geir.slackspace.space;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import tv.geir.slackspace.common.ProminentObject;
import tv.geir.slackspace.common.SlackSpaceException;
import tv.geir.slackspace.communication.InvalidResponseException;
import tv.geir.slackspace.communication.Request;
import tv.geir.slackspace.communication.Response;
import tv.geir.slackspace.matching.Template;
import tv.geir.slackspace.server.ServerLease;

/**
 * Processes requests immediately
 * 
 * @author Geir Gullestad Pettersen
 *
 */
public class RequestProcessor implements IRequestProcessor {

	private SpaceAccessor spaceAccessor;
	
	private static Log log = LogFactory.getLog( RequestProcessor.class );
	
	/**
	 * Creates a RequestProcessor.
	 *
	 */
	public RequestProcessor() {
		
		
		if( log.isInfoEnabled() ) {
			log.info( "RequestProcessor initialized" );
		}
	}
	
	/* (non-Javadoc)
	 * @see tv.geir.slackspace.space.IRequestProcessor#process(tv.geir.slackspace.Request)
	 */
	public Response process(Request request) {
		
		Response res = execute( request );
		
		return res;		
	}
	
	/** 
	 * Executes a request
	 * @param request
	 * @return response to execution of the request
	 */
	public Response execute(Request request) {
		Response res = new Response( request.getUuid() );
		try {			
			long time = request.getLeaseTime();
			if( time < 0 ) {
				time = 0;
			}
			ProminentObject object;
			switch( request.getRequestType() ) {			
				case READ:					
					object = spaceAccessor.read( getTemplate( request ), time );
					res.setData( object );
					break;
				case TAKE:					
					object = spaceAccessor.take( getTemplate( request ), time );
					res.setData( object );
					break;
				case WRITE:
					object = getProminentObject( request );
					if( object.getSerializedObject() == null ) {
						throw new SlackSpaceException( "Invalid entry: null" );
					}
					ServerLease l = spaceAccessor.write( object , time );
					res.setData( l );
					break;
			}
			res.setResponseCode( Response.Code.OK );
		} catch ( Throwable t ) {
			res.setResponseCode( Response.Code.ERROR );
			res.setError( t );
			log.warn( "Error processing request: " + t.getMessage() );
		}
		return res;
	}

	private Template getTemplate(Request req) {
		Object o = req.getData();
		if (o instanceof Template) {
			return (Template) o;
		}
		throw new InvalidResponseException(
				"Request did not contain a object template");
	}

	private ProminentObject getProminentObject( Request req ) {
		Object o = req.getData();
		if( o instanceof ProminentObject ) {
			return ( ProminentObject ) o;
		}
		throw new InvalidResponseException(
		"Request did not contain a mobile object");
	}

	public SpaceAccessor getSpaceAccessor() {
		return spaceAccessor;
	}

	public void setSpaceAccessor(SpaceAccessor spaceAccessor) {
		this.spaceAccessor = spaceAccessor;
	}

	

	

}
